package internal

import (
	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Common/data"
	"GameServer/Common/utils"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	"GameServer/Game/lib"
	"GameServer/Game/m"
	"GameServer/Game/sp"
	"fmt"
)

type ActivityManager struct {
	ActActivityGroup map[int64]map[int64]*m.ActActivityInfo // 激活活动列表,键为活动的typeEnum
}

func StringToBsonObjectId(str string) (b bson.ObjectId) {
	return bson.ObjectIdHex(str)
}

func NewActivityManager() *ActivityManager {
	return &ActivityManager{
		ActActivityGroup: make(map[int64]map[int64]*m.ActActivityInfo, 0),
	}
}

func (am *ActivityManager) Init() {
	// 使用的是和 game/m/activity.go 中激活的活动同样的数据库
	listAccept := make([]*m.ActActivityInfo, 0)
	err := dbmodule.MgoDB.GameDB.FindAll("actActivityGroup", nil, nil, &listAccept)
	if err != nil {
		return
	}
	if am.ActActivityGroup == nil { // 父Map检查
		am.ActActivityGroup = make(map[int64]map[int64]*m.ActActivityInfo, 0)
	}
	for _, act := range listAccept {
		//还原到缓存
		m.Cache.Put("actActivityGroup", act.Id.Hex(), act)
		//还原到上层结构
		actId := act.ActId
		typeEnum := act.TypeEnum
		// 子Map检查
		_, findMap := am.ActActivityGroup[typeEnum]
		if findMap == false {
			am.ActActivityGroup[typeEnum] = make(map[int64]*m.ActActivityInfo)
		}
		// 上层结构赋值
		am.ActActivityGroup[typeEnum][actId] = act
	}
	am.ReCheckActActivityList(nil, nil)
}

func (am *ActivityManager) Run(closeSig chan bool) {

}

func (am *ActivityManager) Destroy() {

}

// 当前是否有激活的老虎机活动，获取时检测一次有效性
func (am *ActivityManager) HasSlotAct() (has bool) {
	has = false
	typeMap, findMap := am.ActActivityGroup[data.ActivityEnum.Slot]
	if findMap {
		if len(typeMap) > 0 {
			for _, act := range typeMap {
				actInTime := lib.IsActActivityInActTime(act)
				if actInTime {
					has = true // 只需要一个激活的，就返回正确
					break
				}
			}
			//-----设计服务器每天0点，重新Recheck，如果是非0点结束的活动就需要强硬检测---
		}
	}
	return has
}

func (am *ActivityManager) GetRankActId() (actId int64, rankRewardId int64, err error) {
	actId = -1
	rankRewardId = -1
	typeMap, findMap := am.ActActivityGroup[data.ActivityEnum.Slot]
	if findMap {
		if len(typeMap) > 0 {
			for _, act := range typeMap {
				actInTime := lib.IsActActivityInActTime(act)
				if actInTime {
					id := act.ActId
					config, err := lib.GetSlotActConfigeTableInfo(id)
					if err == nil {
						if config.RankRewardId != 0 {
							actId = id
							rankRewardId = int64(config.RankRewardId)
							break
						}
					}
				}
			}
		}
	}
	if actId != -1 {
		return actId, rankRewardId, nil
	} else {
		err = errors.NewErrcode(data.Errcode.NotFound, "没有排名活动")
		return -1, rankRewardId, err
	}
}

func (am *ActivityManager) GetActActivity(id string) (act *m.ActActivityInfo, err error) {
	v, isLoad, ok := m.Cache.GetForLoad("actActivityGroup", id)
	if !ok {
		err = errors.NewErrcode(data.Errcode.NotFound, fmt.Sprintf("没有此活动,id:%s", id))
		return
	}

	act = v.(*m.ActActivityInfo)
	if isLoad {
		typeList, findList := am.ActActivityGroup[act.TypeEnum]
		if findList {
			for index, act := range typeList {
				if act.Id.Hex() == id {
					am.ActActivityGroup[act.TypeEnum][index] = act
					break
				}
			}
		}
	}
	return
}

func (am *ActivityManager) GetActActivityByActId(actId int64) (r *m.ActActivityInfo) {
	r = nil
	for _, typeList := range am.ActActivityGroup {
		for _, act := range typeList {
			if act.ActId == actId {
				r = act
				break
			}
		}
	}
	return r
}

func (am *ActivityManager) GetActActivityByTypeAndActId(actId int64, typeEnum int64) (r *m.ActActivityInfo) {
	_, findMap := am.ActActivityGroup[typeEnum]
	if findMap {
		actInfo, findAct := am.ActActivityGroup[typeEnum][actId]
		if findAct {
			return actInfo
		}
	}
	return nil
}

// 根据类型，从缓存中获取所有当前，激活的活动列表
func (am *ActivityManager) GetActActivityByType(typeNum int64) (r map[int64]*m.ActActivityInfo) {
	typeMap, findMap := am.ActActivityGroup[typeNum]
	if findMap {
		return typeMap
	}
	return nil
}

func (am *ActivityManager) GetAndCheckActActivityList() (dMap map[int64]map[int64]*m.ActActivityInfo) {
	dMap = make(map[int64]map[int64]*m.ActActivityInfo, 0)
	nowTime := utils.TNow().Unix()
	for typeNum, typelist := range am.ActActivityGroup { // 遍历所有Type的活动数组
		_, findMap := dMap[typeNum]
		if findMap == false {
			dMap[typeNum] = make(map[int64]*m.ActActivityInfo, 0)
		}
		for _, curAct := range typelist { // 遍历单个Type活动数组
			actId := curAct.ActId
			if nowTime >= curAct.BeginTime && nowTime < curAct.EndTime {
				dMap[typeNum][actId] = curAct
			}
		}
	}
	return dMap
}

func (am *ActivityManager) ReCheckActActivityList(playerOnLineUID []string, broadcastFunc func(list []string, data interface{})) {
	// 检查激活活动，并新增
	delList := make(map[int64]int64, 0)
	ActList, err := lib.GetActActivityList()
	if err == nil {
		if ActList == nil || len(ActList) == 0 {
			//没有活动，清空排名数据，清空玩家进度
		}
		for _, act := range ActList {
			//fmt.Printf("ReCheckActActivityList,actId:%d,begin : %s,end : %s \n", act.ActivId, act.BeginTime, act.EndTime)
			am.AddAct(act)
		}
	} else {
		ActList = make([]data.ActActivity, 0) // 读表出错，重置为无活动
	}
	// 检查不再激活列表内的，废弃活动，并删除
	nowTime := utils.TNow().Unix()
	for _, typelist := range am.ActActivityGroup { // 遍历所有Type的活动数组
		for _, curAct := range typelist { // 遍历单个Type活动数组
			findAct := false
			for _, realAct := range ActList { // 遍历实际的激活活动
				if curAct.ActId == int64(realAct.ActivId) {
					findAct = true
				}
			}
			if nowTime < curAct.BeginTime || nowTime >= curAct.EndTime {
				findAct = false
			}
			if findAct == false {
				delList[curAct.ActId] = curAct.TypeEnum
			}
		}
	}
	if len(delList) > 0 {
		for Key_ActId, Value_TypeEnum := range delList {
			am.RemoveActActivity(Key_ActId, Value_TypeEnum)
		}
	}
	// 推送活动信息，给所有在线的玩家
	if playerOnLineUID != nil && len(playerOnLineUID) > 0 && broadcastFunc != nil {
		activityAll := lib.FormatTotalActActivity(am.ActActivityGroup)
		// 加载委托活动
		if entrActiv, err := lib.GetCurrentEntrustActiv(); err == nil {
			activityAll = append(activityAll, lib.FormatEntrActiv(&entrActiv))
		}
		bData := &sp.ActivityPushTotalRequest{
			ActivityAll: activityAll,
		}
		broadcastFunc(playerOnLineUID, bData)
	}
}

func (am *ActivityManager) AddAct(act data.ActActivity) {
	actId := int64(act.ActivId)
	resetMonth := int64(act.ResetMonth)
	resetWeekDay := int64(act.ResetWeekDay)
	newAct := am.GetActActivityByActId(actId)
	begin_Time, _ := utils.LayoutToTime(act.BeginTime)
	end_Time, _ := utils.LayoutToTime(act.EndTime)
	nowTime := utils.TNow().Unix()
	// typeNum := lib.WhatIsActEnum(actId)
	typeNum := int64(act.ActTyp)
	if newAct == nil {
		newAct = &m.ActActivityInfo{
			Id:           bson.NewObjectId(),
			ActId:        actId,
			TypeEnum:     typeNum,
			BeginTime:    begin_Time.Unix(),
			EndTime:      end_Time.Unix(),
			ResetMonth:   resetMonth,
			ResetWeekDay: resetWeekDay,
		}
		_, findMap := am.ActActivityGroup[typeNum]
		if findMap == false {
			am.ActActivityGroup[typeNum] = make(map[int64]*m.ActActivityInfo)
		}
		if nowTime >= begin_Time.Unix() && nowTime < end_Time.Unix() {
			m.Cache.Put("actActivityGroup", newAct.Id.Hex(), newAct)
			am.ActActivityGroup[typeNum][actId] = newAct
			newAct.UpsetAndUpdate(newAct)
		} else {
			am.RemoveActActivity(actId, typeNum)
		}
	} else {
		newAct.BeginTime = begin_Time.Unix()
		newAct.EndTime = end_Time.Unix()
		newAct.TypeEnum = typeNum
		newAct.ResetMonth = resetMonth
		newAct.ResetWeekDay = resetWeekDay
		am.ActActivityGroup[typeNum][actId] = newAct
		if nowTime >= begin_Time.Unix() && nowTime < end_Time.Unix() {
			m.Cache.Put("actActivityGroup", newAct.Id.Hex(), newAct)
			am.ActActivityGroup[typeNum][actId] = newAct
			newAct.UpsetAndUpdate(newAct)
		} else {
			am.RemoveActActivity(actId, typeNum)
		}
	}
}

func (am *ActivityManager) RemoveActActivity(actId int64, typeNum int64) {
	//查找活动数据
	_, findMap := am.ActActivityGroup[typeNum]
	if findMap {
		act, findact := am.ActActivityGroup[typeNum][actId]
		if findact {
			// 通知单个活动数据层，从Cache,和db删除数据，返回db的错误
			err := act.Delete()
			if err != nil {
				log.WithFields(log.Fields{
					"method":  "RemoveActActivity",
					"typeNum": typeNum,
					"actId":   actId,
				}).Debug(err)
			}
		} else {
			return
		}
	}
	// 删除完后，删除上层结构
	_, findMap = am.ActActivityGroup[typeNum]
	if findMap {
		_, findact := am.ActActivityGroup[typeNum][actId]
		if findact {
			delete(am.ActActivityGroup[typeNum], actId)
		}
	}
}
